from __future__ import with_statement
from BeautifulSoup import BeautifulSoup, SoupStrainer
import sys
import re
import htmlentitydefs
import simplejson

TE_RE = re.compile(r'(?P<course_code>.+?) (?P<course_name>.+) \((?P<math>\d+\.?\d?), (?P<sci>\d+\.?\d?), (?P<engsci>\d+\.?\d?), (?P<engdes>\d+\.?\d?)\)')
CSE_RE = re.compile(r'(?P<course_code>.*?) (?P<course_name>.+)\((?P<weight>\d*)\)')

def unescape(text):
    def fixup(m):
        text = m.group(0)
        if text[:2] == "&#":
            # character reference
            try:
                if text[:3] == "&#x":
                    return unichr(int(text[3:-1], 16))
                else:
                    return unichr(int(text[2:-1]))
            except ValueError:
                pass
        else:
            # named entity
            try:
                text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
            except KeyError:
                pass
        return text # leave as is
    return re.sub("&#?\w+;", fixup, text)

def make_parser(re_pattern):
    def course_to_dict(opt_line):
        c_string = unescape(re.sub('\n', '', opt_line.string))
        result = re_pattern.match(c_string)
        return result.groupdict()

    return course_to_dict

def munge_tech_electives(filename):
    course_filter = SoupStrainer('select', {'name': 'course'})
    with open(filename, 'r') as file_in:
        te_courses = BeautifulSoup(file_in.read(), parseOnlyThese=course_filter)

    course_to_dict = make_parser(TE_RE)

    return map(course_to_dict, te_courses.findAll('option'))

def munge_cse(filename):
    course_filter = SoupStrainer('select', {'name': 'course'})
    with open(filename, 'r') as file_in:
        cses = BeautifulSoup(file_in.read(), parseOnlyThese=course_filter)

    course_lists = [section.findAll('option') for section in cses]

    course_to_dict = make_parser(CSE_RE)

    return {
        'a' : map(course_to_dict, course_lists[0]),
        'b' : map(course_to_dict, course_lists[1]),
        'c' : map(course_to_dict, course_lists[2]),
        'd' : map(course_to_dict, course_lists[3])
    }

def main():
    tes = munge_tech_electives(sys.argv[1])
    cses = munge_cse(sys.argv[2])

    with open('ceab_tech.json', 'w') as tech_out:
        simplejson.dump(tes, tech_out, sort_keys=True, indent=2)

    with open('ceab_complimentary.json', 'w') as comp_out:
        simplejson.dump(cses, comp_out, sort_keys=True, indent=2)

if __name__ == '__main__':
    main()
